package com.teamwings.modules.file.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.io.Files;
import com.teamwings.common.exception.ResultException;
import com.teamwings.modules.file.entity.File;
import com.teamwings.modules.file.mapper.FileMapper;
import com.teamwings.modules.file.service.IFileService;
import com.teamwings.util.CommonUtils;
import com.teamwings.util.MinioUtil;
import com.teamwings.util.ZipUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipOutputStream;

@Service
@Slf4j
public class IFileServiceImpl extends ServiceImpl<FileMapper, File> implements IFileService {

    @Value("${auto-form.minio.bucket-name}")
    private String bucketName;

    @Override
    public File uploadFile(MultipartFile file, String bizPath) {
        // 判断文件大小
        if (StringUtils.isEmpty(bizPath)) {
            // 如果路径为空
            bizPath = DateFormatUtils.format(new Date(), "yyyy/MM/dd");
        }

        String orgName = file.getOriginalFilename();// 获取文件名
        if (StringUtils.isEmpty(orgName)) {
            throw new ResultException("文件名不存在");
        }

        orgName = CommonUtils.getFileName(orgName);
        String fileUrl = MinioUtil.upload(file, bizPath);
        if (StringUtils.isEmpty(fileUrl)) {
            throw new ResultException("上传失败,请检查配置信息是否正确!");
        }

        String fileExtension = Files.getFileExtension(orgName);

        File minioFile = new File();
        minioFile.setFileName(orgName);
        String[] temp = fileUrl.split(bizPath);
        String fileName = temp[1];
        minioFile.setFilePath(bizPath + fileName);
        minioFile.setUrl(fileUrl);
        minioFile.setFileSuffix(fileExtension);

        // 文件信息保存到数据库
        return minioFile;
    }

    @Override
    public void deleteFile(String path) {
        log.info("删除文件：" + path);
        MinioUtil.removeObject(bucketName, path);
    }

    @Override
    public void downloadFile(String path, HttpServletResponse response) {
        InputStream in = MinioUtil.getMinioFile(bucketName, path);
        String fileName = CommonUtils.getFileName(path);
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            int len;
            byte[] b = new byte[1024];
            while ((len = in.read(b)) != -1) {
                os.write(b, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("io异常");
            throw new ResultException("文件下载失败");
        } finally {
            try {
                os.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("io异常");
            }
        }
    }

    @Override
    public void downloadFiles(List<String> pathList, HttpServletResponse response) {
        // 创建临时文件夹
        String tempDir = "\\temp\\file\\";
        java.io.File dir = new java.io.File(tempDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        List<java.io.File> fileList = new ArrayList<>();
        for (String path : pathList) {
            InputStream inputStream = MinioUtil.getMinioFile(bucketName, path);
            String fileName = CommonUtils.getFileName(path);
            String tempFile = tempDir + "\\" + fileName;
            java.io.File file = new java.io.File(tempFile);
            try {
                CommonUtils.inputStream2File(inputStream, file);
            } catch (IOException e) {
                e.printStackTrace();
            }
            fileList.add(file);
        }

        java.io.File firstFile = fileList.get(0);
        String name = firstFile.getName();
        name = name.substring(0, name.indexOf(".")) + "等共" + fileList.size() + "个文件" + ".zip";

        java.io.File file = new java.io.File("\\temp\\zip\\");
        if (!file.exists()) {
            file.mkdirs();
        }
        String tempPath = "\\temp\\zip\\" + name;
        java.io.File zip = new java.io.File(tempPath);
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(zip);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        new ZipOutputStream(outputStream);
        ZipUtil.toZip(fileList, outputStream);
        downloadZip(zip, response);
        // 删除临时文件夹
        file.delete();
    }

    private static HttpServletResponse downloadZip(java.io.File file, HttpServletResponse response) {
        try {
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Length", "" + file.length());
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                java.io.File f = new java.io.File(file.getPath());
                f.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return response;
    }
}
